#include "laurin-scan-result-model.h"
#include "../core/laurin-utils.h"
#include "../core/network/laurin-80211-access-point.h"
#include "../core/network/laurin-80211-station.h"
#include "../core/network/laurin-80211-network.h"
#include "../core/network/laurin-ip-network-client.h"
#include <string>
#include <sstream>

/*--------------------------------------------------------------------------*/

LaurinScanResultModelRecord::LaurinScanResultModelRecord()
{
	add(sequence);
	add(ssid);
	add(bssid);
	add(mac);
	add(ip);
	add(distance);
	add(type);
}




/*--------------------------------------------------------------------------*/

LaurinScanAccessPointModelRecord::LaurinScanAccessPointModelRecord()
{
	add(ssid);
	add(bssid);
	add(distance);
}



Glib::RefPtr<Gtk::ListStore> LaurinScanAccessPointModel::getStore()
{
	if(!_store)
		_store = Gtk::ListStore::create(record);

	return _store;
}


void LaurinScanAccessPointModel::clear()
{
	if(_store)
		_store->clear();
}




/*--------------------------------------------------------------------------*/

LaurinScanResultModel::LaurinScanResultModel()
{
	_networks = NULL;
	_ip_network = NULL;
}


Glib::RefPtr<Gtk::ListStore> LaurinScanResultModel::getStore()
{
	if(!_store)
		_store = Gtk::ListStore::create(record);

	return _store;
}


void LaurinScanResultModel::set80211NetworkSet(Laurin80211NetworkSet* networks)
{
	_networks = networks;
}


void LaurinScanResultModel::setIPNetwork(LaurinIPNetwork* network)
{
	_ip_network = network;
}


LaurinScanAccessPointModel* LaurinScanResultModel::getAccessPointModel()
{
	return &_ap_model;
}


void LaurinScanResultModel::clear()
{
	if(_store)
	{
		_store->clear();
		_ap_model.clear();
	}
}


void LaurinScanResultModel::fillResult()
{
	if(!(_store))
		_store = Gtk::ListStore::create(record);


	_ap_model.clear();
	_store->clear();

	Gtk::TreeModel::Row r;
	Gtk::TreeModel::Row r2;

	int count = 1;


	if(_ip_network != NULL)
	{

		// NETWORK CLIENTS

		std::list<LaurinIPNetworkClient>::iterator ncb = _ip_network->getClients()->begin();
		std::list<LaurinIPNetworkClient>::iterator nce = _ip_network->getClients()->end();

		while(ncb != nce)
		{

			r = *(_store->prepend());
			r[record.sequence] = count++;
			r[record.ssid] = "";
			r[record.bssid] = "";
			r[record.mac] = Glib::ustring(getReadableMAC(ncb->getMAC()));
			r[record.ip] = Glib::ustring(getReadableIP(ncb->getIP()));
			r[record.distance] = "N/A";
			r[record.type] = "Wired Station/Wireless Station not in range";

			ncb++;
		}

	}


	if(_networks != NULL)
	{

		std::list<Laurin80211Network>::iterator nb = _networks->getNetworks()->begin();
		std::list<Laurin80211Network>::iterator ne = _networks->getNetworks()->end();

		// iterate over networks
		while(nb != ne)
		{

			std::list<Laurin80211AccessPoint>::iterator ab = nb->getAccessPoints()->begin();
			std::list<Laurin80211AccessPoint>::iterator ae = nb->getAccessPoints()->end();


			// ACCESS POINTS
			while(ab != ae)
			{

				r2 = *(_ap_model.getStore()->prepend());
				r2[_ap_model.record.ssid] = nb->getSSID();
				r2[_ap_model.record.bssid] = Glib::ustring(getReadableMAC(ab->getBSSID()));

				Gtk::TreeModel::iterator b = _store->children().begin();
				Gtk::TreeModel::iterator e = _store->children().end();

				bool notfound = true;
				u_int8_t* internalmac = generatePreviousMAC(ab->getMAC());
				Glib::ustring readable = Glib::ustring(getReadableMAC(internalmac));
				free(internalmac);

				while(b != e && notfound)
				{

					if((*b)[record.mac] == Glib::ustring(getReadableMAC(ab->getMAC())))
					{
						notfound = false;
					}
					else if((*b)[record.mac] == readable)
						notfound = false;

					else
						b++;
				}

				if(notfound)
				{
					r = *(_store->prepend());
					r[record.sequence] = count++;
					r[record.ip] = "Not in my local network";
				}
				else
					r = *b;


				r[record.ssid] = nb->getSSID();
				r[record.bssid] = Glib::ustring(getReadableMAC(ab->getBSSID()));
				r[record.mac] = Glib::ustring(getReadableMAC(ab->getMAC()));
				r[record.type] = "Access Point";


				if(ab->isLocationAvaible())
				{
					std::ostringstream ss;
					ss << ab->getDistanceFromMonitor();
					r[record.distance] = ss.str();
					r2[_ap_model.record.distance] = ab->getDistanceFromMonitor();
				}
				else
				{
					r[record.distance] = "N/A";
					r2[_ap_model.record.distance] = 0.0;
				}


				ab++;
			}


			std::list<Laurin80211Station>::iterator sb = nb->getStations()->begin();
			std::list<Laurin80211Station>::iterator se = nb->getStations()->end();


			// STATIONS
			while(sb != se)
			{

				Gtk::TreeModel::iterator b = _store->children().begin();
				Gtk::TreeModel::iterator e = _store->children().end();

				bool notfound = true;


				while(b != e && notfound)
				{

					if((*b)[record.mac] == Glib::ustring(getReadableMAC(sb->getMAC())))
					{
						notfound = false;
					}
					else
						b++;
				}

				if(notfound)
				{
					r = *(_store->prepend());
					r[record.sequence] = count++;
					r[record.ip] = "Not in my local network";
				}
				else
					r = *b;


				r[record.ssid] = nb->getSSID();
				r[record.bssid] = Glib::ustring(getReadableMAC(sb->getBSSID()));
				r[record.mac] = Glib::ustring(getReadableMAC(sb->getMAC()));
				r[record.type] = "Wireless Station";


				if(sb->isLocationAvaible())
				{
					std::ostringstream ss;
					ss << ab->getDistanceFromMonitor();
					r[record.distance] = ss.str();
				}
				else
					r[record.distance] = "N/A";

				sb++;
			}


			nb++;
		}

	}

}
